﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.Net.Sockets;
namespace NGE.Net
{
    public class Server
    {
        public Server()
        {
            socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            Clients = new List<Client>();
        }

        Socket socket;
        List<Client> Clients = new List<Client>();

        public event SessionEvent OnSent;
        public event SessionEvent OnReceived;
        public event SessionEvent OnClientConnected;
        public event SessionEvent OnClientDisconnected;
        public event SessionEvent OnDisconnected;

        //int getClientIndex(IntPtr handle)
        //{
        //    for (int i = 0; i < Clients.Count; i++)
        //    {
        //        if (Clients[i].Handle == handle)
        //        {
        //            return i;
        //        }
        //    }
        //    return -1;
        //}
        //public Client this[IntPtr handle]
        //{
        //    get
        //    {
        //        int i = getClientIndex(handle);
        //        if (i < 0)
        //        {
        //            return null;
        //        }
        //        return Clients[i];
        //    }
        //}

        public void Start(int port)
        {
            socket.Bind(new IPEndPoint(IPAddress.Any, port));
            socket.Listen(1);
            socket.BeginAccept(new AsyncCallback(acceptCallback), socket);
        }

        void acceptCallback(IAsyncResult asyncResult)
        {
            Socket serverSocket = (Socket)asyncResult.AsyncState;
            Socket clientSocket = serverSocket.EndAccept(asyncResult);

            int i = ins(new Client(clientSocket, Clients.Count));

            OnClientConnected(Clients[i], null);

            Clients[i].OnSent += new SessionEvent(Client_OnSent);
            Clients[i].OnReceived += new SessionEvent(Client_OnReceived);
            Clients[i].OnDisconnected += new SessionEvent(Client_OnDisconnected);

            Clients[i].StartReceiving();

            socket.BeginAccept(new AsyncCallback(acceptCallback), socket);
        }

        void Client_OnDisconnected(object sender, object arg)
        {
            if (OnClientDisconnected != null)
            {
                OnClientDisconnected(sender, null);
            }
        }

        public void Kick(Client client)
        {
            client.Disconnect();
        }
        void del(int index)
        {
            Clients[index] = null;
        }
        int ins(Client client)
        {
            int i = 0;
            int j = -1;
            for (i = 0; i < Clients.Count; i++)
            {
                if (Clients[i] == null)
                {
                    j = i;
                }
            }
            if (j < 0)
            {
                Clients.Add(client);
                return Clients.Count - 1;
            }
            else
            {
                Clients[j] = client;
                return j;
            }
        }

        public void Stop()
        {
            socket.Disconnect(true);
            if (OnDisconnected != null)
            {
                OnDisconnected(this, null);
            }
        }

        public void Send(Client client, byte[] data)
        {
            client.Send(data);
        }

        public void Send(int clientIndex, byte[] data)
        {
            Clients[clientIndex].Send(data);
        }

        public void Send(byte[] data)
        {
            foreach (Client client in Clients)
            {
                client.Send(data);
            }
        }

        void Client_OnSent(object sender, object arg)
        {
            if (OnSent != null)
            {
                OnSent(sender, arg);
            }
        }

        void Client_OnReceived(object sender, object arg)
        {
            if (OnReceived != null)
            {
                OnReceived(sender, arg);
            }
        }
    }

}
